﻿/* ######################################## *\
 * ### Copyright (C) 2009 AJ Ravindiran ### *
 * ### HTTP://THEAJ.NET/ <AJ@THEAJ.NET> ### *
\* ######################################## */
using System;
using System.IO;
using System.Net.Sockets;
using System.Collections.Generic;

using AJRavindiran.Jolt.RuneScape.Model.Characters;

namespace AJRavindiran.Jolt.RuneScape.Network
{
    /// <summary>
    /// Represents a player socket.
    /// </summary>
    public class PlayerSocket
    {
        #region Fields
        private Character mCharacter;
        private Socket mSocket = null;
        private Stream mStream;
        private TcpClient mTcpClient;

        private const int BUFFER_SIZE = 512;
        #endregion

        #region Properties
        /// <summary>
        /// Gets the number of available bytes.
        /// </summary>
        public int Availible
        {
            get
            {
                try
                {
                    if (mTcpClient == null) return 0;
                    return mTcpClient.Available;
                }
                catch (Exception ex) { throw new Exception("PlayerSocket.Availible Exception", ex); }
            }
        }

        public Stream Stream
        {
            get { return mStream; }
            set { mStream = value; }
        }
        public TcpClient TcpClient
        {
            get { return mTcpClient; }
            set { mTcpClient = value; }
        }
        #endregion

        #region Constructors
        /// <summary>
        /// Constructs a new Player socket for send and recieveing 
        /// data via client (thought a TCP client).
        /// </summary>
        /// <param name="character">The character to create this for.</param>
        /// <param name="socket">The socket transferred from TCPConnection</param>
        public PlayerSocket(Character character, Socket socket)
        {
            // Initialize socket and character fields.
            this.mSocket = socket;
            this.mCharacter = character;

            try
            {
                // Setup a stream socket for listening.
                this.mTcpClient = new TcpClient();
                this.mTcpClient.Client = mSocket;
                this.mStream = mTcpClient.GetStream();
            }
            catch (Exception ex)
            {
                JoltEnvironment.GetLogger().WriteException(ex);
            }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Reads one byte from the socket.
        /// </summary>
        /// <returns>Returns a single byte from the buffer, or -1 if an error occurs.</returns>
        public int Read()
        {
            try
            {
                // If there is not any availible data, or tcpclient is null, return -1.
                if (mTcpClient.Available < 1 || mTcpClient == null) return -1;
                return mStream.ReadByte();
            }
            catch (Exception ex) { throw new Exception("PlayerSocket.Read() Exception", ex); }
        }

        /// <summary>
        /// Reads a given number of bytes from the socket.
        /// </summary>
        /// <param name="size">The number of bytes to read from the buffer.</param>
        /// <returns>Returns the number of bytes that were successfully read.</returns>
        public int Read(int size)
        {
            try
            {
                if (mTcpClient == null) return -1;
                byte[] buffer = mCharacter.GetCodecFactory().GetDecoder().InputBuffer;
                return mStream.Read(buffer, 0, size);
            }
            catch (Exception ex) { throw new Exception("PlayerSocket.Read() Exception", ex); }
        }

        /// <summary>
        /// Writes a byte to the remote host.
        /// </summary>
        /// <param name="value">Writes one byte to the buffer.</param>
        public void Write(byte value)
        {
            try
            {
                if (mTcpClient == null) return;
                mStream.WriteByte(value);
            }
            catch (Exception ex) { throw new Exception("PlayerSocket.Write() Exception", ex); }
        }

        /// <summary>
        /// Writes bytes to the remote host.
        /// </summary>
        /// <param name="buffer">Array to write bytes from.</param>
        /// <param name="start">The position in the array to start writing at.</param>
        /// <param name="finish">The last position of the array to stop writing at.</param>
        public void Write(byte[] buffer, int start, int finish)
        {
            try
            {
                if (mTcpClient == null) return;
                mStream.Write(buffer, start, finish);
            }
            catch (Exception ex) { throw new Exception("PlayerSocket.Write() Exception", ex); }
        }

        /// <summary>
        /// Clear all buffers.
        /// </summary>
        public void Flush()
        {
            try
            {
                if (mTcpClient == null) return;
                mStream.Flush();
            }
            catch (Exception ex) { throw new Exception("PlayerSocket.Flush() Exception", ex); }
        }
        #endregion
    }
}
